package Service;

import Algorithm.Recommended;
import Entities.DoeBookEntity;
import DAO.RecommendDao;
import com.opensymphony.xwork2.ActionContext;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.apache.struts2.ServletActionContext;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Transactional
public class RecommendService
{
    private Recommended recommended;
    private RecommendDao recommendDao;
    private List<String> recommendResult;  //这个列表中储存的元素格式是：图书id：评分
    private String user_name;
    private String cacheKey;
    private String userRecResultKey;
    private String sessionCacheKey;
    private Cache hasRecommendCache;
    private Cache recommendResultCache;
    public RecommendDao getRecommendDao() {
        return recommendDao;
    }

    public void setRecommendDao(RecommendDao recommendDao) {
        this.recommendDao = recommendDao;
    }

    public Recommended getRecommended() {
        return recommended;
    }

    public void setRecommended(Recommended recommended) {
        this.recommended = recommended;
    }

    //推荐函数，返回推荐图书列表
    public List<DoeBookEntity> recommend(String userName, int after_id, int limit, String session_Id)
    {
//        String sessionID = ServletActionContext.getRequest().getSession().getId();
        String sessionID = session_Id;
        boolean isInit = false;
        user_name = userName;
        cacheKey = user_name+" has recommend_";
        sessionCacheKey = user_name + " last sessionID";
        userRecResultKey = user_name+ " recommendResult";
        hasRecommendCache = CacheManager.getCacheManager("__DEFAULT__").getCache("HasRecommendCache");
        recommendResultCache = CacheManager.getCacheManager("__DEFAULT__").getCache("RecommendResultCache");

        if (recommendResultCache.get(userRecResultKey) == null)
        {
            recommendResult = recommended.recommend(user_name);
            recommendResultCache.put(new Element(userRecResultKey,recommendResult));
        }
        else
        {
            Element resultElement = recommendResultCache.get(userRecResultKey);
            recommendResult = (List<String>) resultElement.getObjectValue();
        }



        Element lastSessionElement = recommendResultCache.get(sessionCacheKey);
        if (lastSessionElement == null)
            isInit = true;
        else if (lastSessionElement.getObjectValue() != sessionID)
            isInit = true;
        if (isInit)
            initRecommendList(hasRecommendCache);

        List<String> ids = new ArrayList<>();
        List<String> counts = new ArrayList<>();
        int resultIndex = 0;
        for (int i = 0;i<limit;i++){
            int index = i + after_id;
            String result;
            Element resultElement = hasRecommendCache.get(cacheKey+String.valueOf(index));
            if (resultElement == null){
                result = recommendResult.get(0);
                hasRecommendCache.put(new Element(cacheKey+String.valueOf(index),result));
                recommendResult.remove(result);
                resultIndex++;
            }else {
                result = (String) resultElement.getObjectValue();
            }
            String [] bundle = result.split(":");
            ids.add(bundle[0]);
            counts.add(bundle[1]);
        }

        recommendResultCache.remove(userRecResultKey);
        recommendResultCache.put(new Element(userRecResultKey,recommendResult));
        recommendResultCache.remove(sessionCacheKey);
        recommendResultCache.put(new Element(sessionCacheKey,sessionID));
        return recommendDao.bookListByIds(ids);
    }//end function recommend()

    private void initRecommendList(Cache has_recommendCache){
        List<String> cacheKeys = has_recommendCache.getKeys();

        for (String key : cacheKeys){
            if (!key.startsWith(cacheKey))
                continue;
            else {
                has_recommendCache.remove(key);
            }
        }
    }


    public void refreshRecommend()
    {
        recommendResult = recommended.recommend(user_name);
        hasRecommendCache.removeAll();
        recommendResultCache.remove(userRecResultKey);
        recommendResultCache.put(new Element(userRecResultKey,recommendResult));
    }


}
